/*
 * Title:        CloudScheduler Toolkit
 * Description:  a Toolkit for Modeling and Simulation of Job Scheduling and Resource Provisioning in Cloud System
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 * Author:       Fuhui Wu
 *
 * Copyright (c) 2013-2014, The National University of Defense Technology, China
 */

package org.nudt.jCloud.workload;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.nudt.jCloud.infrastructure.SlotType;
import org.nudt.jCloud.util.ExponentialDistribution;

public class BatchWLGen implements WorkloadGenerator{
	private int xJobCount;
	private double avgJobInterarrivalTime;
	private double avgTaskDuration;
	private double jobSizeDistribution;
	private int maxTaskNumPerJob;
	private SlotType slotType;

	public BatchWLGen(int jobCount, 
			double avgJobInterarrivalTime, 
			double avgTaskDuration, 
			double jobSizeDistribution,
			int maxTaskNumPerJob, 
			SlotType slotType) {
		setXJobCount(jobCount);
		setAvgJobInterarrivalTime(avgJobInterarrivalTime);
		setMaxTaskNumPerJob(maxTaskNumPerJob);
		setJobSizeDistribution(jobSizeDistribution);
		setAvgTaskDuration(avgTaskDuration);
		setSlotType(slotType);
	}
	
	public Workload generate(double startTime){
		Workload workload = new Workload();
		ExponentialDistribution jobArrivalTimeGen = new ExponentialDistribution(avgJobInterarrivalTime);
		ExponentialDistribution avgTaskDurationGen = new ExponentialDistribution(avgTaskDuration);
		Random taskNumR = new Random(System.currentTimeMillis());
		double arrivalTime = startTime;
		for(int i=0; i<xJobCount; ++i){
			arrivalTime += jobArrivalTimeGen.sample();
			List<Task> taskList = new ArrayList<Task>();
			double duration = avgTaskDurationGen.sample();
			int taskNum = 0;
			if(maxTaskNumPerJob <= 1){
				taskNum = 1;
			}else{
				if(taskNumR.nextDouble()<=jobSizeDistribution){
					taskNum = taskNumR.nextInt(maxTaskNumPerJob/2)+1;
				}else{
					taskNum = taskNumR.nextInt(maxTaskNumPerJob/2)+maxTaskNumPerJob/2+1;
				}				
			}
			for(int j=0; j<taskNum; ++j){
				taskList.add(new Task(j, duration));
			}
			LogicalJob andJob = new AllJob(arrivalTime, workload);
			andJob.add(new BatchJob(arrivalTime, taskList, slotType, andJob));
			workload.add(andJob);
		}
		return workload;
	}

	public double getAvgJobInterarrivalTime() {
		return avgJobInterarrivalTime;
	}

	public void setAvgJobInterarrivalTime(double avgJobInterarrivalTime) {
		this.avgJobInterarrivalTime = avgJobInterarrivalTime;
	}

	public double getAvgTaskDuration() {
		return avgTaskDuration;
	}

	public void setAvgTaskDuration(double avgTaskDuration) {
		this.avgTaskDuration = avgTaskDuration;
	}

	public SlotType getSlotType() {
		return slotType;
	}

	public void setSlotType(SlotType slotType) {
		this.slotType = slotType;
	}

	public int getXJobCount() {
		return xJobCount;
	}

	public void setXJobCount(int xJobCount) {
		this.xJobCount = xJobCount;
	}

	public double getJobSizeDistribution() {
		return jobSizeDistribution;
	}

	public void setJobSizeDistribution(double jobSizeDistribution) {
		this.jobSizeDistribution = jobSizeDistribution;
	}

	public int getMaxTaskNumPerJob() {
		return maxTaskNumPerJob;
	}

	public void setMaxTaskNumPerJob(int maxTaskNumPerJob) {
		this.maxTaskNumPerJob = maxTaskNumPerJob;
	}
}
